using System;

using System.Configuration;
using System.Windows.Forms;
using System.IO;

namespace Wrath.Configuration
{
    public sealed class ConfigurationWorker
    {
        private System.Configuration.Configuration config;        

        /// <summary>
        /// Default constructor. Opens the configuration file of the Applications executable.
        /// </summary>
        public ConfigurationWorker()
        {            
            config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath + ".config");
        }

        /// <summary>
        /// This constructor opens the configuration file at the specified location.
        /// </summary>
        /// <param name="configurationExePath">The path to the configuration file of the associated executable.</param>
        public ConfigurationWorker(string configurationExePath)
        {
            config = ConfigurationManager.OpenExeConfiguration(configurationExePath);
        }

        /// <summary>
        /// An indexer that gets and sets appSetting settings.
        /// </summary>
        /// <param name="appSetting">The Setting Name</param>
        /// <returns>The string value of the setting.</returns>
        public string this[string appSetting]
        {
            get
            {
                if (config.AppSettings.Settings[appSetting] != null)
                {
                    return config.AppSettings.Settings[appSetting].Value;
                }

                return null;
            }
            set
            {
                if (config.AppSettings.Settings[appSetting] == null)
                {
                    config.AppSettings.Settings.Add(appSetting, value);
                }
                else
                {
                    config.AppSettings.Settings[appSetting].Value = value;
                }

                config.AppSettings.SectionInformation.ForceSave = true;
            }
        }

        /// <summary>
        /// Gets a setting from the appSettings section.
        /// </summary>
        /// <param name="settingName">The name/key of the setting to retrieve.</param>
        /// <returns>The requested value or null.</returns>
        public string GetSetting(string settingName)
        {
            if (config.AppSettings.Settings[settingName] != null)
            {
                return config.AppSettings.Settings[settingName].Value;
            }

            return null;
        }

        /// <summary>
        /// Gets a setting from the specified section.
        /// </summary>
        /// <param name="sectionName">The name of the section to retrieve settings from.</param>
        /// <param name="settingName">The name/key of the setting to retrieve.</param>
        /// <returns>The requested value or null.</returns>
        public string GetSetting(string sectionName, string settingName)
        {
            KeyValueConfigurationSection section = (KeyValueConfigurationSection)config.Sections[sectionName];
            if (section == null) return null;

            if (section.Settings[settingName] != null)
            {
                return section.Settings[settingName].Value;
            }

            return null;
        }

        /// <summary>
        /// Sets the speified setting in the appSettings section.
        /// </summary>
        /// <param name="settingName">The name of the setting to set. If the setting does not exist, it is added.</param>
        /// <param name="settingValue">The value of the setting.</param>
        /// <returns>true.</returns>
        public bool SetSetting(string settingName, string settingValue)
        {
            if (config.AppSettings.Settings[settingName] == null)
            {
                config.AppSettings.Settings.Add(settingName, settingValue);
            }
            else
            {
                config.AppSettings.Settings[settingName].Value = settingValue;
            }

            config.AppSettings.SectionInformation.ForceSave = true;

            return true;
        }

        /// <summary>
        /// Sets the speified setting in the appSettings section.
        /// </summary>
        /// <param name="sectionName">The name of the section to set settings in.</param>
        /// <param name="settingName">The name of the setting to set. If the setting does not exist, it is added.</param>
        /// <param name="settingValue">The value of the setting.</param>
        /// <returns>true if the setting was set correctly.</returns>
        public bool SetSetting(string sectionName, string settingName, string settingValue)
        {
            KeyValueConfigurationSection section = (KeyValueConfigurationSection)config.Sections[sectionName];
            if (section == null)
            {
                section = new KeyValueConfigurationSection();
                config.Sections.Add(sectionName, section);
            }
            
            if (section.Settings[settingName] == null)
            {
                section.Settings.Add(settingName, settingValue);
            }
            else
            {
                section.Settings[settingName].Value = settingValue;
            }

            section.SectionInformation.ForceSave = true;

            return true;
        }

        /// <summary>
        /// Adds a new section to the configuration file.
        /// </summary>
        /// <param name="sectionName">The name of the section to add.</param>
        /// <param name="section">The KeyValueConfigurationSection to add.</param>
        public void AddSection(string sectionName, KeyValueConfigurationSection section)
        {
            config.Sections.Add(sectionName, section);
        }

        /// <summary>
        /// Writes the configuration to file.
        /// </summary>
        public void Save()
        {
            config.Save();
        }
    }
}
